package com.mathdroid.gui.componentlist;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;

import javax.swing.JPanel;
import javax.swing.JScrollPane;

/**
 * This component list consists of heavy weight JComponents. Each cell extends
 * JPanel. You can scroll through the list, it extends JScrollPane. The content
 * panel of the JScrollPane contains every cell.
 */
public final class ComponentList extends JScrollPane {

	/**
	 * Default UID.
	 */
	private static final long serialVersionUID = 1L;
	
	/**
	 * The content panel of this JScrollPane.
	 */
	private final JPanel contentPane = new JPanel();
	
	/**
	 * The renderer class is used to create cell instances. Implement the
	 * interface to create cells/JPanels. Each cell knows their model element.
	 */
	private IComponentListCellRenderer renderer = null;
	
	/**
	 * The component list model contains the model elements. Elements do not
	 * know about their view.
	 */
	private IComponentListModel model = null;
	
	/**
	 * The component constraints for this list.
	 */
	private GridBagConstraints constraints = new GridBagConstraints();
	
	/**
	 * The space between cells.
	 */
	private static final int SPACING = 3;

	/**
	 * Create a new ComponentList. This can be used like a normal JScrollPane.
	 */
	public ComponentList() {
		super();
		
		final JPanel p = new JPanel(new BorderLayout());
		
		this.contentPane.setLayout(new GridBagLayout());
		this.contentPane.setBackground(Color.WHITE);
		
		p.setBackground(Color.WHITE);
		p.add(this.contentPane, BorderLayout.NORTH);
		this.getViewport().add(p);
	}
	
	/**
	 * Set the model of this ComponentList. Implement the interface to create
	 * a model instance.
	 * @param m Model.
	 */
	public void setComponentListModel(final IComponentListModel m) {
		this.model = m;
	}
	
	/**
	 * Set the cell renderer. The cell renderer is used to create JPanel 
	 * instances.
	 * @param r Cell renderer.
	 */
	public void setComponentListCellRenderer(
			final IComponentListCellRenderer r) {
		this.renderer = r;
	}
	
	/**
	 * Add an element to the list.
	 * @param e Element to add to this list.
	 */
	public void addElement(final AComponentListElement e) {
		final int index = this.model.addElement(e);
		e.setIndex(index);
		
		Cell c = this.renderer.getInstance(e);
		
		this.constraints.gridx = 0;
		this.constraints.gridy = index;
		this.constraints.fill = GridBagConstraints.HORIZONTAL;
		this.constraints.weighty = 0;
		this.constraints.weightx = 1;
		this.constraints.insets = new Insets(0, 0, SPACING, 0);
		
		this.contentPane.add(c, this.constraints);
		
		this.validate();
		this.repaint();
	}
	
	/**
	 * Remove an element from this list.
	 * @param e Element to remove.
	 */
	public void removeElement(final AComponentListElement e) {
		final int index = this.model.removeElement(e);
		this.contentPane.remove(index);
		
		this.validate();
		this.repaint();
	}
	
	/**
	 * Remove all elements from the list.
	 */
	public void removeElements() {
		this.model.clear();
		this.contentPane.removeAll();
		
		this.validate();
		this.repaint();
	}
}
